<?php
declare(strict_types=1);

namespace app\admin\controller;

use aphp\core\Jump;
use aphp\core\Tool;

// 主题管理
class Themes
{
    use Jump;

    protected string $middleware = 'rbac';
    protected string $api_url; // 远程api地址
    protected string $dir_tpl; // 主题模板目录
    protected string $dir_res; // 模板资源目录

    public function __construct()
    {
        $this->api_url = 'https://api.aphpcms.com';
        $this->dir_tpl = ROOT_PATH . '/template';
        $this->dir_res = ROOT_PATH . '/public/static/themes';
    }

    // 远程主题页面
    public function online()
    {
        if ($this->isAjax()) {
            $themes = array_values($this->api_theme_online());
            $this->_json(200, '', $themes, ['count' => count($themes)]);
        }
        return view();
    }

    // API获取远程主题列表
    public function api_theme_online(): array
    {
        $online = get_curl($this->api_url . '/theme/index');
        if (!empty($online) && json_validate($online)) {
            $ret = json_decode($online, true);
            if ($ret['status'] == 1) {
                $installed = array_filter(scandir($this->dir_tpl), fn(string $file): bool => is_dir($this->dir_tpl . '/' . $file) && $file != '.' && $file != '..');
                foreach ($ret['data'] as &$vo) {
                    $vo['show'] = in_array($vo['sign'], $installed) ? 4 : 5;
                }
                return $ret['data'];
            }
        }
        return [];
    }

    // 获取主题下载地址
    protected function get_down_url(string $name): string
    {
        $ret = get_curl($this->api_url . '/theme/zip?name=' . $name);
        if (!empty($ret) && json_validate($ret)) {
            $ret = json_decode($ret, true);
            return $ret['data']['file'] ?? '';
        }
        return '';
    }

    // 安装主题
    public function install(string $name)
    {
        $zip_file = $this->dir_tpl . '/aphp.' . $name . '.zip';
        if (!file_exists($zip_file)) {
            // 远程下载文件
            $down_url = $this->get_down_url($name);
            if (!empty($down_url)) {
                if (!$this->download($down_url, $zip_file)) {
                    $this->error('下载安装包失败，请稍后再试！');
                }
            } else {
                $this->error('主题安装包文件不存在');
            }
        }
        if (is_dir($this->dir_tpl . '/' . $name . '/')) {
            $this->error('主题已存在，请卸载后再安装！');
        }
        $zip = new \ZipArchive();
        if ($zip->open($zip_file) === TRUE) {
            $zip->extractTo($this->dir_tpl . '/' . $name . '/');
            $zip->close();
            Tool::dir_move($this->dir_tpl . '/' . $name . '/_assets/', $this->dir_res . '/' . $name . '/');
            // 更新主题ini配置
            $online = $this->api_theme_online();
            if (isset($online[$name])) {
                $online[$name]['image'] = '/static/themes/' . $name . '/screenshot.jpg';
                unset($online[$name]['show']);
                file_put_contents($this->dir_tpl . '/' . $name . '/ini.php', "<?php\nreturn " . var_export($online[$name], true) . ';');
            }
            $this->success('主题安装成功', 'index');
        }
        $this->error('主题安装失败');
    }

    // 下载安装包
    protected function download(string $url, string $save_file): bool
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_REFERER, $this->api_url);
        $file_content = curl_exec($ch);
        curl_close($ch);
        if ($file_content !== false && $file_content != '405') {
            return (bool)file_put_contents($save_file, $file_content);
        }
        return false;
    }

    // 获取前台当前主题
    protected function get_current_theme(): string
    {
        $theme = [];
        $theme_file = ROOT_PATH . '/app/index/config/theme.php';
        if (file_exists($theme_file)) {
            $theme = require $theme_file;
        }
        return $theme['name'] ?? 'default';
    }

    // 设置前台使用主题
    protected function set_current_theme(string $name): bool
    {
        if (!is_dir($this->dir_tpl . '/' . $name)) {
            return false;
        }
        $theme_file = ROOT_PATH . '/app/index/config/theme.php';
        Tool::dir_init(dirname($theme_file));
        $theme = ['name' => $name];
        return (bool)file_put_contents($theme_file, "<?php\nreturn " . var_export($theme, true) . ';');
    }

    // 本地主题页面
    public function index()
    {
        if ($this->isAjax()) {
            $themes = array_values($this->api_theme_local());
            $this->_json(200, '', $themes, ['count' => count($themes)]);
        }
        return view();
    }

    // 设置(使用)前台主题
    public function use(string $name)
    {
        $r = $this->set_current_theme($name);
        $this->_jump(['主题设置成功', '请先安装此主题'], $r);
    }

    // 获取本地主题列表
    public function api_theme_local(): array
    {
        $local = []; // 本地主题信息
        // 当前主题
        $current_theme = $this->get_current_theme();
        // 获取远程主题列表
        $online = $this->api_theme_online();
        // 本地目录信息
        $dir = $this->dir_tpl;
        $list = array_diff(scandir($dir), ['.', '..']);
        $local_zip = [];
        foreach ($list as $file) {
            if (is_dir("$dir/$file") && file_exists("$dir/$file/ini.php")) {
                // 读取本地主题信息
                $local[$file] = include "$dir/$file/ini.php";
                if ($current_theme == $file) {
                    $local[$file]['sort'] = 0;
                    $local[$file]['show'] = 1;
                } else {
                    $local[$file]['show'] = 2;
                }
                // 比效版本
                if (isset($online[$file]['version']) && isset($local[$file]['version'])) {
                    if (version_compare($local[$file]['version'], $online[$file]['version'], '<')) {
                        // 更新标识
                        $local[$file]['new'] = 1;
                    }
                }
            } elseif (preg_match('/aphp.(.*).zip/', $file, $match)) {
                $local_zip[] = $match[1]; //本地安装包
            }
        }
        foreach ($local_zip as $sign) {
            if (isset($local[$sign])) {
                // 本地主题(已安装，有安装包)
                $local[$sign]['show'] = ($current_theme == $sign) ? 1 : 2;
            } elseif (isset($online[$sign])) {
                // 本地主题安装包(未安装)，在线主题列表中
                $local[$sign] = $online[$sign];
                $local[$sign]['show'] = 3;
            } else {
                // 本地主题安装包(未安装)，不在线主题列表中
                $local[$sign] = [
                    'id' => 0,
                    'sign' => $sign,
                    'title' => $sign . '主题',
                    'image' => '/static/thumb/1.jpg',
                    'intro' => '此模板为自定主题！',
                    'version' => '1.0',
                    'price' => '免费',
                    'author' => '未知(待安装)',
                    'link' => 'https://www.aphpcms.com',
                    'sort' => 9999,
                    'time' => date('Y-m-d'),
                    'show' => 3
                ];
            }
        }
        uasort($local, function ($a, $b) {
            return $a['sort'] <=> $b['sort'];
        });
        return $local;
    }

    // 添加自定义主题
    public function add(array $req)
    {
        if ($this->isPost()) {
            $sign = $req['sign'];
            $theme_path = Tool::dir_init($this->dir_tpl . '/' . $sign);
            if (file_exists($theme_path . '/ini.php')) {
                $this->error('该主题已存在！');
            }
            $req['id'] = 0;
            $req['image'] = '/static/themes/' . $sign . '/screenshot.jpg';
            $req['price'] = $req['price'] > 0 ? '￥' . $req['price'] : '免费';
            $req['sort'] = 9999;
            $req['time'] = date('Y-m-d');
            file_put_contents($theme_path . '/ini.php', "<?php\nreturn " . var_export($req, true) . ';');
            $res_path = Tool::dir_init($this->dir_res . '/' . $sign);
            Tool::file_copy(ROOT_PATH . '/public/static/themes/screenshot.jpg', $res_path);
            $this->success('主题添加成功！', 'index');
        }
        return view();
    }

    // 导出主题
    public function export(string $name)
    {
        $zip_file = $this->dir_tpl . '/aphp.' . $name . '.zip';
        if (file_exists($zip_file)) {
            unlink($zip_file);
        }
        Tool::dir_copy($this->dir_res . '/' . $name, $this->dir_tpl . '/' . $name . '/_assets');
        $phar = new \PharData($zip_file);
        $phar->buildFromDirectory($this->dir_tpl . '/' . $name);
        Tool::dir_delete($this->dir_tpl . '/' . $name . '/_assets', true);
        $this->success('主题导出成功！文件：template/aphp.' . $name . '.zip');
    }

    // 卸载主题
    public function uninstall(string $name)
    {
        if ($name == 'default') {
            $this->error('默认主题不允许卸载');
        }
        if (!is_dir($this->dir_tpl . '/' . $name)) {
            $this->error('此主题未安装');
        }
        Tool::dir_delete($this->dir_res . '/' . $name, true);
        Tool::dir_delete($this->dir_tpl . '/' . $name, true);
        $this->success('主题卸载成功');
    }

    // 删除主题
    public function delete(string $name)
    {
        if ($name == 'default') {
            $this->error('默认主题不允许删除');
        }
        $zip_file = $this->dir_tpl . '/aphp.' . $name . '.zip';
        !file_exists($zip_file) || unlink($zip_file);
        $this->success('删除成功');
    }

    // 更新主题
    public function update(string $name)
    {
        Tool::dir_delete($this->dir_res . '/' . $name, true);
        Tool::dir_delete($this->dir_tpl . '/' . $name, true);
        $zip_file = $this->dir_tpl . '/aphp.' . $name . '.zip';
        !file_exists($zip_file) || unlink($zip_file);
        $this->install($name);
    }
}